﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Principal;
using System.Security.AccessControl;
using System.Diagnostics;
namespace DDFolderSync
{
    public static class FileUtils
    {
        public static bool IsProcessRunning(string name)
        {
            try
            {
                return Process.GetProcesses().Any(prc => prc.ProcessName.Contains(name));
            }
            catch (Exception ex)
            {

                Trace.TraceError("Error querying process " + name + " " + ex.Message);

                return false;
            }

        }
        public static void SetFullControlDirectoryPermissions(string absolutePath)
        {

            var sec = Directory.GetAccessControl(absolutePath);
            sec.AddAccessRule(new FileSystemAccessRule(new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
            Directory.SetAccessControl(absolutePath, sec);
        }

        public static void SetModifyDirectoryPermissions(string absolutePath)
        {
            DirectorySecurity sec = Directory.GetAccessControl(absolutePath);
            SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
            sec.AddAccessRule(new FileSystemAccessRule(everyone,
                FileSystemRights.Modify | FileSystemRights.Synchronize,
                InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                PropagationFlags.None,
                AccessControlType.Allow));
            Directory.SetAccessControl(absolutePath, sec);

        }

        public static DirectorySecurity GetDirectorySecurity(string absolutePath)
        {
           return Directory.GetAccessControl(absolutePath);
         
        }

        public static void SetDirectorySecurity(string absolutePath, DirectorySecurity dirSec)
        {
             Directory.SetAccessControl(absolutePath, dirSec);

        }
        public static void SetFileSystemRights(string absolutePath, FileSystemRights fileRights)
        {
            DirectorySecurity sec = Directory.GetAccessControl(absolutePath);
            SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
            sec.AddAccessRule(new FileSystemAccessRule(everyone,
               fileRights,
                InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                PropagationFlags.None,
                AccessControlType.Allow));
            Directory.SetAccessControl(absolutePath, sec);

        }
        /// <summary>
        /// Checks if the file is in use
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool IsFileInUse(string absoluteFilePath)
        {
            // If the file can be opened for exclusive access it means that the file
            // is no longer locked by another process.
            try
            {
                using (FileStream inputStream = File.Open(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    return false;
                }
            }
            catch (IOException)
            {
                return true;
            }
        }
        /// <summary>
        /// Reads the file by giving other processes rights to read/write
        /// </summary>
        /// <param name="absoluteFilePath"></param>
        /// <returns></returns>
        public static byte[] ReadFileWithoutLocking(string absoluteFilePath)
        {

            return ReadFileBytes(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);

        }

        /// <summary>
        /// Reads the file by giving other processes rights to read/write
        /// </summary>
        /// <param name="absoluteFilePath"></param>
        /// <returns></returns>
        public static string ReadFileWithoutLockingAsString(string absoluteFilePath)
        {
            return ReadFileAsString(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);

        }

        /// <summary>
        /// Reads the file with full lock
        /// </summary>
        /// <param name="absoluteFilePath"></param>
        /// <returns></returns>
        public static byte[] ReadFileWithLocking(string absoluteFilePath)
        {

            return ReadFileBytes(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.None);

        }

        /// <summary>
        /// Reads the file with full lock
        /// </summary>
        /// <param name="absoluteFilePath"></param>
        /// <returns></returns>
        public static string ReadFileWithLockingAsString(string absoluteFilePath)
        {
            return ReadFileAsString(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.None);

        }

     
        public static byte[] ReadFileBytes(string absoluteFilePath, FileMode openInthisMode, FileAccess accessAllowedAfterReading, FileShare sharingToAllow)
        {

            byte[] buffer;
            using (FileStream fileStream = new FileStream(absoluteFilePath, openInthisMode, accessAllowedAfterReading, sharingToAllow))
            {

                int length = (int)fileStream.Length;  // get file length
                buffer = new byte[length];            // create buffer
                int count;                            // actual number of bytes read
                int sum = 0;                          // total number of bytes read

                // read until Read method returns 0 (end of the stream has been reached)
                while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
                    sum += count;  // sum is a buffer offset for next reading
            }
            return buffer;

        }

        public static string ReadFileAsString(string absoluteFilePath,FileMode openInthisMode, FileAccess accessAllowedAfterReading, FileShare sharingToAllow)
        {
            string s = null;

            using (FileStream fileStream = new FileStream(absoluteFilePath, openInthisMode, accessAllowedAfterReading, sharingToAllow))
            {

                using (StreamReader sr = new StreamReader(fileStream))
                {

                    s = sr.ReadToEnd();
                }

            }
            return s;

        }

        public static string CreateRebootTrackerFile(string fileName, out bool newFileCreated)
        {
            newFileCreated = false;
            
            if (!File.Exists(fileName))
            {

                fileName = File.Create(fileName).Name;
                newFileCreated = true;
            }

            return fileName;
        }

        public static bool IsReboot(string trackerFileName)
        {
            return File.Exists(trackerFileName);

        }

    }
}
